package componentes.flor;

import java.awt.Color;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.media.opengl.GL;
import javax.swing.JOptionPane;

import properties.Config;
import transformaciones.TAfin;
import utils.SistemaCoordenadas;

import componentes.Componente3D;
import componentes.ComponenteCompuesto3D;
import componentes.flor.estambres.Base;
import componentes.flor.estambres.Cabeza;

import constantes.Consts;
import figuras.BSplines;
import figuras.PuntoVector;
import figuras.malla.MallaContornoSpline;
import figuras.malla.MallaMediaRevolucion;

public class Estambre extends ComponenteCompuesto3D {

	private ArrayList<Color> colores;
	private Base base;
	private Cabeza cabeza;

	public Estambre(Base base, Cabeza cabeza, ArrayList<BSplines> bsplines,
			GL gl) {
		super();
		this.bsplines = bsplines;
		this.gl = gl;
		matriz = new TAfin(this.gl);
		this.componentes = new ArrayList<Componente3D>();
		this.colores = new ArrayList<Color>();
		this.componentes.add(base);
		this.componentes.add(cabeza);
		this.base = base;
		this.cabeza = cabeza;
	}

	public Estambre(GL gl, File file, double xRight, double grosor) throws IOException,
			IndexOutOfBoundsException, FileNotFoundException {
		this.gl = gl;
		matriz = this.getMatriz();
		this.componentes = new ArrayList<Componente3D>();
		this.colores = new ArrayList<Color>();
		this.bsplines = new ArrayList<BSplines>();
		this.cargar(file, xRight, grosor);
		base = null;
		cabeza = null;
	}

	public void guardar(File file) throws IOException,
			IndexOutOfBoundsException, FileNotFoundException {
		DataOutputStream oos = new DataOutputStream(new BufferedOutputStream(
				new FileOutputStream(file)));
		for (int i = 0; i < componentes.size(); i++) {
			Color colorComp = componentes.get(i).getColor();
			oos.writeInt(colorComp.getRed());
			oos.writeInt(colorComp.getGreen());
			oos.writeInt(colorComp.getBlue());
			ArrayList<PuntoVector> puntosControl = this.bsplines.get(i)
					.getPuntosControl();
			oos.writeInt(puntosControl.size());
			for (PuntoVector p : puntosControl) {
				oos.writeDouble(p.getX());
				oos.writeDouble(p.getY());
				oos.writeDouble(p.getZ());
			}
		}
		oos.close();
	}

	private void cargar(File file, double xRight, double grosor) throws IOException,
			FileNotFoundException {
		DataInputStream ois;
		ois = new DataInputStream(new BufferedInputStream(new FileInputStream(
				file)));
		for (int j = 0; j < 2; j++) {
			int red = ois.readInt();
			int green = ois.readInt();
			int blue = ois.readInt();
			colores.add(new Color(red, green, blue));
			ArrayList<PuntoVector> puntosControl = new ArrayList<PuntoVector>();
			int numPuntos = ois.readInt();
			for (int i = 0; i < numPuntos; i++) {
				double x = ois.readDouble();
				double y = ois.readDouble();
				double z = ois.readDouble();
				puntosControl.add(new PuntoVector(x, y, z, 1));
			}
			BSplines b = new BSplines();
			b.setPuntosControl(puntosControl);
			b.perfilaSpline();
			this.bsplines.add(b);
		}
		ois.close();
		this.creaEstambre(xRight,grosor);
	}

	private void creaEstambre(double xRight, double grosor) {
		double radianes = 0;
		int pasos = 0, lados = 0;
		try {
			for (int i = 0; i < 2; i++) {
				PuntoVector p1 = this.bsplines.get(1).getPerfil().get(0);
				PuntoVector p2 = this.bsplines.get(1).getPerfil().get(
						this.bsplines.get(1).getPerfil().size() - 1);
				PuntoVector v = p1.obtenVector(p2);
				PuntoVector u = v.perpendicularIzquierda();
				PuntoVector c = p1;
				Config config;

				config = Config.getInstance();
				lados = config.getInteger("estambre.lados.poligono");
				//grosor = config.getDouble("estambre.grosor");
				radianes = config
						.getDouble("estambre.radianes.mediaRevolucion");
				pasos = config.getInteger("estambre.pasos.mediaRevolucion");
				double factor = grosor / 1.8;
				this.bsplines.get(1).setPuntosControl(
						SistemaCoordenadas.changePointsCoordinateSystemEscala(
								this.bsplines.get(1).getPuntosControl(), u, v,
								c, ((3 * xRight) / 5) * factor));
			}
			base = new Base(new MallaContornoSpline(lados, this.bsplines.get(0)
					.getPerfil().size(), grosor, this.bsplines.get(0), gl),
					this.bsplines, gl);
			base.setColor(colores.get(0));
			cabeza = new Cabeza(new MallaMediaRevolucion(this.bsplines.get(1)
					.getPuntosControl(), radianes, pasos), this.bsplines, gl);
			cabeza.setColor(colores.get(1));
			this.colocaCabeza();
			componentes.add(base);
			componentes.add(cabeza);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "Error",
					"Error creando estambre", JOptionPane.ERROR_MESSAGE);
			e.printStackTrace();
		}

	}

	public void colocaCabeza() {
		PuntoVector p1 = bsplines.get(1).getPerfil().get(0);
		PuntoVector p2 = bsplines.get(0).getPerfil().get(
				bsplines.get(0).getPerfil().size() - 1);
		PuntoVector vectorTraslacion = p1.obtenVector(p2);
		cabeza.getMatriz().trasladar(
				vectorTraslacion.getX() - Consts.DESPLAZAMIENTO_CABEZA,
				vectorTraslacion.getY(), vectorTraslacion.getZ());
		cabeza.getMatriz().rotarZ(-90);
		cabeza.getMatriz().rotarY(-90);
	}

}
